#include "gazell_params_cfg.h"
#if (ROLE == HOST)
#include "gzp.h"
#include "gzll.h"
#include "string.h"
#include "stdint.h"
#include "stdbool.h"
#include "wdt.h"

//-----------------------------------------------------------------------------
// Internal (static) functions
//-----------------------------------------------------------------------------
static void gzp_process_address_req(uint8_t* gzp_req);

//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
static  bool gzp_pairing_enabled_f = false;                     /*<主机配对标志*/
static  bool gzp_address_exchanged_f = false;                   /*<主机和设备地址交换完成标志*/
static uint8_t system_address[GZP_SYSTEM_ADDRESS_WIDTH];        /*<主机地址*/

// ==================================================================
/// @brief  : 主机配网前必须调用
// ==================================================================
void gzp_init(void)
{
    // 恢复默认跳频表
    uint8_t chan[] = GZLL_DEFAULT_CHANNEL_TAB;
    gzll_set_channels(chan, GZLL_DEFAULT_CHANNEL_TAB_SIZE);

    gzp_pairing_enabled_f = false;
    gzp_address_exchanged_f = false;

    // Infinite RX timeout
    gzll_set_param(GZLL_PARAM_RX_TIMEOUT, 0);
}

// ==================================================================
/// @brief  : 主机配网使能控制
/// @param  : enable 是否使能
// ==================================================================
void gzp_pairing_enable(bool enable)
{
    gzll_states_t temp_gzll_state;

    temp_gzll_state = gzll_get_state();

    if (gzp_pairing_enabled_f != enable) {
        gzll_goto_idle();

        gzp_pairing_enabled_f = enable;

        if (temp_gzll_state == GZLL_HOST_ACTIVE) {
            gzll_rx_start();
        }
    }
}

// ==================================================================
/// @brief  : 执行Gazell配对库主机操作
// ==================================================================
void gzp_host_execute(void)
{
    uint8_t rx_pipe;
    uint8_t payload_length;
    uint8_t rx_payload[GZLL_MAX_FW_PAYLOAD_LENGTH];

    if (!gzp_pairing_enabled_f)                         /*<配对不使能就不执行*/
        return;
    gzp_address_exchanged_f = false;

    rx_pipe = gzll_get_rx_data_ready_pipe_number();

    if ((rx_pipe == GZP_PAIRING_PIPE)) {
        gzll_rx_fifo_read(rx_payload, &payload_length, NULL);
        switch (rx_payload[0]) {
            case GZP_CMD_HOST_ADDRESS_REQ:              /*<收到设备地址请求了*/
                gzp_process_address_req(rx_payload);    /*<在等待完成和设备的交互*/
                break;
            case GZP_CMD_FETCH_RESP:
            default:
                break;
        }
    }

    // Restart reception if "not proximity backoff" period has elapsed
    if (gzll_get_state() == GZLL_IDLE) {
        gzll_set_param(GZLL_PARAM_RX_TIMEOUT, 0);
        if (gzp_pairing_enabled_f) {
            gzll_set_param(GZLL_PARAM_RX_PIPES, gzll_get_param(GZLL_PARAM_RX_PIPES) | (1 << GZP_PAIRING_PIPE));
        }
        gzll_rx_start();
    }
}

// ==================================================================
/// @brief  : 处理从设备接收到的系统地址请求
/// @param  : gzp_req 接收到的数据
// ==================================================================
static void gzp_process_address_req(uint8_t* gzp_req)
{
    uint8_t temp_rx_pipes, temp_host_mode;
    uint8_t pairing_resp[GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH];

    gzp_address_exchanged_f = false;

    gzll_goto_idle();
    temp_rx_pipes = gzll_get_param(GZLL_PARAM_RX_PIPES);
    temp_host_mode =  gzll_get_param(GZLL_PARAM_HOST_MODE);

    // If requesting Device within close proximity
    if (gzll_rx_power_high()) {
        gzll_set_param(GZLL_PARAM_RX_PIPES, 0);
        gzll_set_param(GZLL_PARAM_HOST_MODE, 0);
        gzll_set_param(GZLL_PARAM_RX_TIMEOUT, GZP_CLOSE_PROXIMITY_BACKOFF_RX_TIMEOUT);
        gzll_rx_fifo_flush();

        // Start "proximity" back off period
        gzll_rx_start();

        while (gzll_get_state() != GZLL_IDLE) {
            port_feed_wdt();
        }

        // Build pairing response packet
        pairing_resp[0] = GZP_CMD_HOST_ADDRESS_RESP;
        port_host_chip_id_read(&pairing_resp[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH);
        gzll_ack_payload_write(&pairing_resp[0], GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH, 0);
        gzll_set_param(GZLL_PARAM_RX_TIMEOUT, GZP_STEP1_RX_TIMEOUT);

        // Enable only pairing pipe when waiting for pairing request step 1
        gzll_set_param(GZLL_PARAM_RX_PIPES, (1 << GZP_PAIRING_PIPE));
        gzll_rx_start();

        while (gzll_get_state() != GZLL_IDLE) {
            port_feed_wdt();
            if (gzll_rx_fifo_read(&gzp_req[0], NULL, NULL)) {
                // Validate step 1 of pairing request
                if (gzp_req[0] == GZP_CMD_HOST_ADDRESS_FETCH) {
                    gzp_address_exchanged_f = true;
                }
            }
        }

        gzll_tx_fifo_flush();
        gzll_rx_fifo_flush();
        gzll_set_param(GZLL_PARAM_RX_TIMEOUT, 0);
        gzll_set_param(GZLL_PARAM_RX_PIPES, temp_rx_pipes);
        gzll_set_param(GZLL_PARAM_HOST_MODE, temp_host_mode);

        gzp_update_radio_params(system_address);
        // Return to normal operation
        gzll_rx_start();
    } else {
        gzll_set_param(GZLL_PARAM_RX_PIPES, temp_rx_pipes & ~(1 << GZP_PAIRING_PIPE));
        gzll_set_param(GZLL_PARAM_RX_TIMEOUT, GZP_NOT_PROXIMITY_BACKOFF_RX_TIMEOUT);
        // Start "not proximity" backoff period
        gzll_rx_start();
    }
}

// ==================================================================
/// @brief  : 获取数据交换状态，主机配对完成标志获取
/// @returns: true or false
// ==================================================================
bool gzp_address_exchanged(void)
{
    return gzp_address_exchanged_f;
}

#endif
